package ckw.gui;

import java.util.List;
import java.util.Properties;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import ckw.database.model.Election;
import ckw.database.model.Member;
import ckw.database.model.Node;
import ckw.database.model.Voter;
import ckw.manager.ManagerController;
import core.cards.election.gui.DlgElectionResult;
import core.cards.election.model.ElectionBackend;
import core.database.NodeType;
import core.exceptions.CommunicationInitiationException;
import core.exceptions.ObjectDeleteException;
import core.exceptions.ObjectUpdateException;
import core.exceptions.PortInUseException;
import core.exceptions.WrongActionException;
import core.utils.ConfigPropertiesHolder;
import core.utils.Converter;
import core.utils.DialogPositioner;
import core.utils.Property;

/**
 * @author DoomThrower
 * 
 */
@Component
public class MainWindow implements ApplicationContextAware {
	private static final Logger LOGGER = LoggerFactory.getLogger(MainWindow.class);

	private static class ContentProvider implements IStructuredContentProvider {
		@Override
		public Object[] getElements(Object inputElement) {
			return new Object[0];
		}

		@Override
		public void dispose() {
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	}

	private static class CommunicationTreeContentProvider implements ITreeContentProvider {
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}

		public void dispose() {
		}

		public Object[] getElements(Object inputElement) {
			return getChildren(inputElement);
		}

		public Object[] getChildren(Object parentElement) {
			return ((Node) parentElement).getChildren().toArray();
		}

		public Object getParent(Object element) {
			return ((Node) element).getParent();
		}

		public boolean hasChildren(Object element) {
			return getChildren(element).length > 0;
		}
	}

	protected Shell shlMain;
	private static ManagerController manager;
	private ApplicationContext context;
	public static final Properties PROPERTIES = new Properties();

	private TabFolder tbFldMain;
	private TabFolder tbFldData;
	private TabFolder tbFldPoll;

	private TreeViewer treeVwrCommunicationNodes;

	private TableViewer tblVwrDataMember;
	private TableViewer tblVwrDataVoter;

	private TableViewer tblVwrPollManage;

	private Button btnAddNode;
	private Button btnEditNode;
	private Button btnDeleteNode;

	private Button btnDataAddMember;
	private Button btnDataEditMember;
	private Button btnDataDeleteMember;

	private Button btnDataAddVoter;
	private Button btnDataEditVoter;
	private Button btnDataDeleteVoter;

	private Button btnPollAddElection;
	private Button btnPollEditElection;
	private Button btnPollDeleteElection;
	private Button btnPollSendElection;
	private Button btnPollManageTokens;
	private Button btnCheckElectionState;
	private Button btnCheckResults;

	private DlgElectionState dlgElectionState;

	/**
	 * Launch the application.
	 * 
	 * @param args
	 */

	public MainWindow() {
		LOGGER.debug("Tworzę MainWindow");
		LOGGER.debug("Utworzono MainWindow");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.context = applicationContext;
	}

	public static ManagerController getManager() {
		return manager;
	}

	/**
	 * @wbp.parser.entryPoint Open the window.
	 */
	public void open() {
		LOGGER.debug("Otwieram MainWindow");
		final Display display = Display.getDefault();

		manager = context.getBean(ManagerController.class);
		try {
			manager.setUp();
		} catch (CommunicationInitiationException e) {
			LOGGER.error(e.getMessage());
		} catch (PortInUseException e) {
			LOGGER.error(e.getMessage());
		}
		createContents();
		shlMain.open();
		shlMain.layout();

		while (!shlMain.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}

		manager.shutDown();
	}

	public Node askForMainNodeData() {
		Node node = null;
		
		NodeType[] nodeTypes = new NodeType[] { NodeType.CKW };
		Node mainNode = new Node();
		mainNode.setNodeType(NodeType.CKW);

		WzdAddEditNode wzdAddEditNode = new WzdAddEditNode(true, mainNode, nodeTypes);
		WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditNode);
		wzdDlg.open();
		if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
			node = mainNode;
		}
		
		return node;
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		createShlMain();
		createMenu();

		tbFldMain = new TabFolder(shlMain, SWT.NONE);
		tbFldMain.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				refreshSelectedPage();
			}
		});
		tbFldMain.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		createCommunicationTab(tbFldMain);
		createDataTab(tbFldMain);
		createPollTab(tbFldMain);

		createStatusComposite();
	}

	private void createShlMain() {
		shlMain = new Shell();
		shlMain.setMinimumSize(new Point(640, 480));
		shlMain.setSize(1024, 800);
		shlMain.setLocation(5, 5);
		Node mainNode = manager.getMainNode();
		if(mainNode == null) {
			shlMain.setText("Daj Głos - CKW");
		} else {
			shlMain.setText("Daj Głos - CKW: " + mainNode.getName() + "[" + mainNode.getLocatorURI() + "]");
		}
		shlMain.setLayout(new GridLayout(1, false));
	}

	private void createMenu() {
		Menu menu = new Menu(shlMain, SWT.BAR);
		shlMain.setMenuBar(menu);

		MenuItem mntmFile = new MenuItem(menu, SWT.CASCADE);
		mntmFile.setText("File");

		Menu menuFile = new Menu(mntmFile);
		mntmFile.setMenu(menuFile);

		MenuItem mntmConfigure = new MenuItem(menuFile, SWT.NONE);
		mntmConfigure.setText("Configure");

		new MenuItem(menuFile, SWT.SEPARATOR);

		MenuItem mntmClose = new MenuItem(menuFile, SWT.NONE);
		mntmClose.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				shlMain.close();
			}
		});
		mntmClose.setText("Close");
	}

	private void createCommunicationTab(TabFolder tbFldMain) {
		TabItem tbtmCommunication = new TabItem(tbFldMain, SWT.NONE);
		tbtmCommunication.setText("Communication");

		Composite cmpCommunication = new Composite(tbFldMain, SWT.NONE);
		tbtmCommunication.setControl(cmpCommunication);
		cmpCommunication.setLayout(new GridLayout(2, false));

		createCommunicationTabTreeViewer(cmpCommunication);
		createCommunicationTabButtons(cmpCommunication);
	}

	private void createCommunicationTabTreeViewer(Composite cmp) {
		treeVwrCommunicationNodes = new TreeViewer(cmp, SWT.BORDER);
		treeVwrCommunicationNodes.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				IStructuredSelection selection = (IStructuredSelection) event.getSelection();
				if (selection.isEmpty()) {
					btnAddNode.setToolTipText("You must select a Node, to which you want to add the new Node.");
					btnEditNode.setToolTipText("You must select a Node, which you want to edit.");
					btnDeleteNode.setToolTipText("You must select a Node, which you want to delete.");
				} else {
					Node selectedNode = getSelectedCommunicationNode();
					if (selectedNode.getNodeType() == NodeType.RKW) {
						btnAddNode.setToolTipText("You can not add a Node to RKW Node.");
					} else {
						btnAddNode.setToolTipText("");
					}
					if (selectedNode.getChildren().isEmpty() == false) {
						btnDeleteNode.setToolTipText("You can only delete Nodes that have no children.");
					} else {
						btnDeleteNode.setToolTipText("");
					}
					btnEditNode.setToolTipText("");
				}
			}
		});
		Tree treeCommunicationNode = treeVwrCommunicationNodes.getTree();
		treeCommunicationNode.setLinesVisible(true);
		treeCommunicationNode.setHeaderVisible(true);
		treeCommunicationNode.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		TreeViewerColumn treeVwrCommunicationNodeName = new TreeViewerColumn(treeVwrCommunicationNodes, SWT.NONE);
		treeVwrCommunicationNodeName.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Node) element).getName();
			}
		});
		TreeColumn trclmnName = treeVwrCommunicationNodeName.getColumn();
		trclmnName.setWidth(250);
		trclmnName.setText("Name");

		TreeViewerColumn treeVwrCommunicationNodeType = new TreeViewerColumn(treeVwrCommunicationNodes, SWT.NONE);
		treeVwrCommunicationNodeType.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Node) element).getNodeType().toString();
			}
		});
		TreeColumn trclmnType = treeVwrCommunicationNodeType.getColumn();
		trclmnType.setResizable(false);
		trclmnType.setWidth(50);
		trclmnType.setText("Type");

		TreeViewerColumn treeVwrCommunicationNodeUri = new TreeViewerColumn(treeVwrCommunicationNodes, SWT.NONE);
		treeVwrCommunicationNodeUri.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Node) element).getLocatorURI();
			}
		});
		TreeColumn trclmnUri = treeVwrCommunicationNodeUri.getColumn();
		trclmnUri.setWidth(125);
		trclmnUri.setText("URI");

		TreeViewerColumn treeVwrCommunicationNodeState = new TreeViewerColumn(treeVwrCommunicationNodes, SWT.NONE);
		treeVwrCommunicationNodeState.setLabelProvider(new ColumnLabelProvider() {
			public Image getImage(Object element) {
				java.awt.Color nodeStateColor = ((Node) element).getState().getColor();
				Image img = createNodeStatusImage(nodeStateColor.getRed(), nodeStateColor.getBlue(), nodeStateColor.getGreen());
				return img;
			}

			public String getText(Object element) {
				return "";
			}
		});
		TreeColumn trclmnState = treeVwrCommunicationNodeState.getColumn();
		trclmnState.setResizable(false);
		trclmnState.setWidth(50);
		trclmnState.setText("State");

		TreeViewerColumn treeVwrCommunicationNodeUpToDate = new TreeViewerColumn(treeVwrCommunicationNodes, SWT.NONE);
		treeVwrCommunicationNodeUpToDate.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				if (element == null) {
					return "";
				} else {
					return ((Node) element).getUpToDate() == true ? "Yes" : "No";
				}
			}
		});
		TreeColumn trclmnUpToDate = treeVwrCommunicationNodeUpToDate.getColumn();
		trclmnUpToDate.setAlignment(SWT.CENTER);
		trclmnUpToDate.setWidth(90);
		trclmnUpToDate.setText("Up to date");
		trclmnUpToDate.setResizable(false);

		treeVwrCommunicationNodes.setContentProvider(new CommunicationTreeContentProvider());
	}

	private void createCommunicationTabButtons(Composite cmp) {
		Composite cmpCommunicationButtons = new Composite(cmp, SWT.NONE);
		cmpCommunicationButtons.setLayout(new FillLayout(SWT.VERTICAL));
		GridData gd_cmpCommunicationButtons = new GridData(SWT.FILL, SWT.TOP, false, false, 1, 1);
		gd_cmpCommunicationButtons.widthHint = 160;
		cmpCommunicationButtons.setLayoutData(gd_cmpCommunicationButtons);

		btnAddNode = new Button(cmpCommunicationButtons, SWT.NONE);
		btnAddNode.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				IStructuredSelection selection = (IStructuredSelection) treeVwrCommunicationNodes.getSelection();
				if (selection.isEmpty() == false) {
					Node selectedNode = getSelectedCommunicationNode();
					if (selectedNode.getNodeType() != NodeType.RKW) {
						onAddNode(selectedNode);
					}
				}
			}
		});
		btnAddNode.setText("Add Node");

		btnEditNode = new Button(cmpCommunicationButtons, SWT.NONE);
		btnEditNode.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				IStructuredSelection selection = (IStructuredSelection) treeVwrCommunicationNodes.getSelection();
				if (selection.isEmpty() == false) {
					Node selectedNode = getSelectedCommunicationNode();
					onEditNode(selectedNode);
				}
			}
		});
		btnEditNode.setText("Edit Node");

		btnDeleteNode = new Button(cmpCommunicationButtons, SWT.NONE);
		btnDeleteNode.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Node selectedNode = getSelectedCommunicationNode();
				try {
					if (selectedNode != null) {
						manager.deleteNode(selectedNode);
					}
				} catch (ObjectDeleteException e) {
					MessageDialog.openError(shlMain, "Error", e.getMessage());
				}

				treeVwrCommunicationNodes.refresh();
			}
		});
		btnDeleteNode.setText("Delete Node");

		new Label(cmpCommunicationButtons, SWT.SEPARATOR | SWT.HORIZONTAL);

		Button btnGenerateConfig = new Button(cmpCommunicationButtons, SWT.NONE);
		btnGenerateConfig.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				manager.sendConfigurations();
			}
		});
		btnGenerateConfig.setToolTipText("Generates Configuration File(s) for communication purposes");
		btnGenerateConfig.setText("Generate Config");

	}

	private void createDataTab(TabFolder tbFldMain) {
		TabItem tbtmData = new TabItem(tbFldMain, SWT.NONE);
		tbtmData.setText("Data");

		Composite cmpData = new Composite(tbFldMain, SWT.NONE);
		tbtmData.setControl(cmpData);
		cmpData.setLayout(new GridLayout(1, false));

		tbFldData = new TabFolder(cmpData, SWT.NONE);
		tbFldData.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		tbFldData.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				refreshSelectedPage();
			}
		});

		createDataMemberTab(tbFldData);
		createDataVoterTab(tbFldData);
	}

	private void createDataMemberTab(TabFolder tbFldData) {
		TabItem tbtmMember = new TabItem(tbFldData, SWT.NONE);
		tbtmMember.setText("Member");

		Composite cmpDataMember = new Composite(tbFldData, SWT.NONE);
		tbtmMember.setControl(cmpDataMember);
		cmpDataMember.setLayout(new GridLayout(2, false));

		createDataMemberTabTableViewer(cmpDataMember);
		createDataMemberTabButtons(cmpDataMember);
	}

	private void createDataMemberTabTableViewer(Composite cmp) {
		tblVwrDataMember = new TableViewer(cmp, SWT.BORDER | SWT.FULL_SELECTION);
		tblVwrDataMember.addSelectionChangedListener(new ISelectionChangedListener() {
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				IStructuredSelection selection = (IStructuredSelection) event.getSelection();
				if (selection.isEmpty()) {
					btnDataEditMember.setToolTipText("You must select a Member, which you want to edit.");
					btnDataDeleteMember.setToolTipText("You must select a Member, which you want to delete.");
				} else {
					btnDataEditMember.setToolTipText("");
					btnDataDeleteMember.setToolTipText("");
				}
			}
		});
		Table tblDataMember = tblVwrDataMember.getTable();
		tblDataMember.setHeaderVisible(true);
		tblDataMember.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		tblVwrDataMember.setContentProvider(new ContentProvider() {
			@SuppressWarnings("unchecked")
			public Object[] getElements(Object inputElement) {
				return ((List<Member>) inputElement).toArray();
			}
		});

		TableViewerColumn tblVwrClmnMemberName = new TableViewerColumn(tblVwrDataMember, SWT.NONE);
		tblVwrClmnMemberName.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Member) element).getName();
			}
		});
		TableColumn tblClmnMemberName = tblVwrClmnMemberName.getColumn();
		tblClmnMemberName.setWidth(125);
		tblClmnMemberName.setText("Name");

		TableViewerColumn tblVwrClmnMemberSurname = new TableViewerColumn(tblVwrDataMember, SWT.NONE);
		tblVwrClmnMemberSurname.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Member) element).getSurname();
			}
		});
		TableColumn tblClmnMemberSurname = tblVwrClmnMemberSurname.getColumn();
		tblClmnMemberSurname.setWidth(190);
		tblClmnMemberSurname.setText("Surname");

		TableViewerColumn tblVwrClmnMemberAddress = new TableViewerColumn(tblVwrDataMember, SWT.NONE);
		tblVwrClmnMemberAddress.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Member) element).getAddress();
			}
		});
		TableColumn tblClmnMemberAddress = tblVwrClmnMemberAddress.getColumn();
		tblClmnMemberAddress.setWidth(250);
		tblClmnMemberAddress.setText("Address");

		TableViewerColumn tblVwrClmnMemberIdentificationField = new TableViewerColumn(tblVwrDataMember, SWT.NONE);
		tblVwrClmnMemberIdentificationField.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Member) element).getIdentificationField();
			}
		});
		TableColumn tblClmnMemberIdentificationField = tblVwrClmnMemberIdentificationField.getColumn();
		tblClmnMemberIdentificationField.setWidth(190);
		tblClmnMemberIdentificationField.setText("Identification field");
	}

	private void createDataMemberTabButtons(Composite cmp) {
		Composite cmpDataMemberButtons = new Composite(cmp, SWT.NONE);
		cmpDataMemberButtons.setLayout(new FillLayout(SWT.VERTICAL));
		GridData gd_cmpDataMemberButtons = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
		gd_cmpDataMemberButtons.widthHint = 160;
		cmpDataMemberButtons.setLayoutData(gd_cmpDataMemberButtons);

		btnDataAddMember = new Button(cmpDataMemberButtons, SWT.NONE);
		btnDataAddMember.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Member newMember = new Member();
				WzdAddEditMember wzdAddEditMember = new WzdAddEditMember(true, newMember);

				WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditMember);
				wzdDlg.open();

				if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
					try {
						manager.storeMember(newMember);
					} catch (ObjectUpdateException e) {
						MessageDialog.openError(shlMain, "Error", e.getMessage());
					}
					refreshSelectedPage();
				}
			}
		});
		btnDataAddMember.setText("Add Member");

		btnDataEditMember = new Button(cmpDataMemberButtons, SWT.NONE);
		btnDataEditMember.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Member selectedMember = getSelectedDataMember();
				if (selectedMember != null) {
					WzdAddEditMember wzdAddEditMember = new WzdAddEditMember(false, selectedMember);

					WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditMember);
					wzdDlg.open();

					if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
						try {
							manager.storeMember(selectedMember);
						} catch (ObjectUpdateException e) {
							MessageDialog.openError(shlMain, "Error", e.getMessage());
						}
						refreshSelectedPage();
					}
				}
			}
		});
		btnDataEditMember.setText("Edit Member");

		btnDataDeleteMember = new Button(cmpDataMemberButtons, SWT.NONE);
		btnDataDeleteMember.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Member selectedMember = getSelectedDataMember();
				if (selectedMember != null) {
					try {
						manager.deleteMember(selectedMember);
					} catch (ObjectDeleteException e) {
						MessageDialog.openError(shlMain, "Error", e.getMessage());
					}
					refreshSelectedPage();
				}
			}
		});
		btnDataDeleteMember.setText("Delete Member");
	}

	private void createDataVoterTab(TabFolder tbFldData) {
		TabItem tbtmVoter = new TabItem(tbFldData, SWT.NONE);
		tbtmVoter.setText("Voter");

		Composite cmpDataVoter = new Composite(tbFldData, SWT.NONE);
		tbtmVoter.setControl(cmpDataVoter);
		cmpDataVoter.setLayout(new GridLayout(2, false));

		createDataVoterTabTableViewer(cmpDataVoter);
		createDataVoterTabButtons(cmpDataVoter);
	}

	private void createDataVoterTabTableViewer(Composite cmpDataVoter) {
		tblVwrDataVoter = new TableViewer(cmpDataVoter, SWT.BORDER | SWT.FULL_SELECTION);
		tblVwrDataVoter.addSelectionChangedListener(new ISelectionChangedListener() {
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				IStructuredSelection selection = (IStructuredSelection) event.getSelection();
				if (selection.isEmpty()) {
					btnDataEditVoter.setToolTipText("You must select a Voter, which you want to edit.");
					btnDataDeleteVoter.setToolTipText("You must select a Voter, which you want to delete.");
				} else {
					btnDataEditVoter.setToolTipText("");
					btnDataDeleteVoter.setToolTipText("");
				}
			}
		});
		Table tblDataVoter = tblVwrDataVoter.getTable();
		tblDataVoter.setHeaderVisible(true);
		tblDataVoter.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		tblVwrDataVoter.setContentProvider(new ContentProvider() {
			@SuppressWarnings("unchecked")
			public Object[] getElements(Object inputElement) {
				return ((List<Voter>) inputElement).toArray();
			}
		});

		TableViewerColumn tblVwrClmnVoterName = new TableViewerColumn(tblVwrDataVoter, SWT.NONE);
		tblVwrClmnVoterName.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Voter) element).getName();
			}
		});
		TableColumn tblClmnVoterName = tblVwrClmnVoterName.getColumn();
		tblClmnVoterName.setWidth(125);
		tblClmnVoterName.setText("Name");

		TableViewerColumn tblVwrClmnVoterSurname = new TableViewerColumn(tblVwrDataVoter, SWT.NONE);
		tblVwrClmnVoterSurname.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Voter) element).getSurname();
			}
		});
		TableColumn tblClmnVoterSurname = tblVwrClmnVoterSurname.getColumn();
		tblClmnVoterSurname.setWidth(190);
		tblClmnVoterSurname.setText("Surname");

		TableViewerColumn tblVwrClmnVoterIdentificationField = new TableViewerColumn(tblVwrDataVoter, SWT.NONE);
		tblVwrClmnVoterIdentificationField.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Voter) element).getIdentificationField();
			}
		});
		TableColumn tblClmnVoterIdentificationField = tblVwrClmnVoterIdentificationField.getColumn();
		tblClmnVoterIdentificationField.setWidth(190);
		tblClmnVoterIdentificationField.setText("Identification field");

		TableViewerColumn tblVwrClmnVoterSex = new TableViewerColumn(tblVwrDataVoter, SWT.NONE);
		tblVwrClmnVoterSex.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Voter) element).getSex().toString();
			}
		});
		TableColumn tblClmnVoterSex = tblVwrClmnVoterSex.getColumn();
		tblClmnVoterSex.setWidth(125);
		tblClmnVoterSex.setText("Sex");

		TableViewerColumn tblVwrClmnVoterAdress = new TableViewerColumn(tblVwrDataVoter, SWT.NONE);
		tblVwrClmnVoterAdress.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Voter) element).getAddress();
			}
		});
		TableColumn tblClmnVoterAdress = tblVwrClmnVoterAdress.getColumn();
		tblClmnVoterAdress.setWidth(250);
		tblClmnVoterAdress.setText("Address");

		TableViewerColumn tblVwrClmnRKW = new TableViewerColumn(tblVwrDataVoter, SWT.NONE);
		tblVwrClmnRKW.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				Voter voter = (Voter) element;
				if (voter == null || voter.getNode() == null) {
					return "";
				} else {
					return voter.getNode().getName();
				}
			}
		});
		TableColumn tblClmnRKW = tblVwrClmnRKW.getColumn();
		tblClmnRKW.setWidth(100);
		tblClmnRKW.setText("RKW");
	}

	private void createDataVoterTabButtons(Composite cmpDataVoter) {
		Composite cmpDataVoterButtons = new Composite(cmpDataVoter, SWT.NONE);
		cmpDataVoterButtons.setLayout(new FillLayout(SWT.VERTICAL));
		GridData gd_cmpDataVoterButtons = new GridData(SWT.FILL, SWT.TOP, false, true, 1, 1);
		gd_cmpDataVoterButtons.widthHint = 160;
		cmpDataVoterButtons.setLayoutData(gd_cmpDataVoterButtons);

		btnDataAddVoter = new Button(cmpDataVoterButtons, SWT.NONE);
		btnDataAddVoter.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Voter newVoter = new Voter();
				WzdAddEditVoter wzdAddEditVoter = new WzdAddEditVoter(true, newVoter);

				WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditVoter);
				wzdDlg.open();

				if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
					try {
						manager.storeVoter(newVoter);
					} catch (ObjectUpdateException e) {
						MessageDialog.openError(shlMain, "Error", e.getMessage());
					}

					refreshSelectedPage();
				}
			}
		});
		btnDataAddVoter.setText("Add Voter");

		btnDataEditVoter = new Button(cmpDataVoterButtons, SWT.NONE);
		btnDataEditVoter.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Voter selectedVoter = getSelectedDataVoter();
				if (selectedVoter != null) {
					WzdAddEditVoter wzdAddEditVoter = new WzdAddEditVoter(false, selectedVoter);

					WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditVoter);
					wzdDlg.open();

					if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
						try {
							manager.storeVoter(selectedVoter);
						} catch (ObjectUpdateException e) {
							MessageDialog.openError(shlMain, "Error", e.getMessage());
						}
						refreshSelectedPage();
					}
				}
			}
		});
		btnDataEditVoter.setText("Edit Voter");

		btnDataDeleteVoter = new Button(cmpDataVoterButtons, SWT.NONE);
		btnDataDeleteVoter.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Voter selectedVoter = getSelectedDataVoter();
				if (selectedVoter != null) {
					try {
						manager.deleteVoter(selectedVoter);
						refreshSelectedPage();
					} catch (ObjectDeleteException e) {
						MessageDialog.openError(shlMain, "Error", e.getMessage());
					}
				}
			}
		});
		btnDataDeleteVoter.setText("Delete Voter");
	}

	private void createPollTab(TabFolder tbFldMain) {
		TabItem tbtmPoll = new TabItem(tbFldMain, SWT.NONE);
		tbtmPoll.setText("Poll");

		Composite cmpPoll = new Composite(tbFldMain, SWT.NONE);
		tbtmPoll.setControl(cmpPoll);
		cmpPoll.setLayout(new GridLayout(1, false));

		tbFldPoll = new TabFolder(cmpPoll, SWT.NONE);
		tbFldPoll.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		tbFldPoll.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				refreshSelectedPage();
			}
		});

		createPollManageTab(tbFldPoll);
		// createPollCurrentTab(tbFldPoll);
	}

	private void createPollManageTab(TabFolder tbFldPoll) {
		TabItem tbtmManage = new TabItem(tbFldPoll, SWT.NONE);
		tbtmManage.setText("Manage");

		Composite cmpPollManage = new Composite(tbFldPoll, SWT.NONE);
		tbtmManage.setControl(cmpPollManage);
		cmpPollManage.setLayout(new GridLayout(2, false));

		createPollManageTabTableViewer(cmpPollManage);
		createPollManageTabButtons(cmpPollManage);
	}

	private void createPollManageTabTableViewer(Composite cmpPollManage) {
		tblVwrPollManage = new TableViewer(cmpPollManage, SWT.BORDER | SWT.FULL_SELECTION);
		Table tblPollManage = tblVwrPollManage.getTable();
		tblPollManage.setHeaderVisible(true);
		tblPollManage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		TableViewerColumn tblVwrClmnElectionName = new TableViewerColumn(tblVwrPollManage, SWT.NONE);
		tblVwrClmnElectionName.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Election) element).getName();
			}
		});
		TableColumn tblClmnElectionName = tblVwrClmnElectionName.getColumn();
		tblClmnElectionName.setWidth(250);
		tblClmnElectionName.setText("Name");

		TableViewerColumn tblVwrClmnElectionStartDate = new TableViewerColumn(tblVwrPollManage, SWT.NONE);
		tblVwrClmnElectionStartDate.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : Converter.dateToString(((Election) element).getStartDate());
			}
		});
		TableColumn tblClmnElectionStartDate = tblVwrClmnElectionStartDate.getColumn();
		tblClmnElectionStartDate.setResizable(false);
		tblClmnElectionStartDate.setWidth(150);
		tblClmnElectionStartDate.setText("Start Date");

		TableViewerColumn tblVwrClmnElectionEndDate = new TableViewerColumn(tblVwrPollManage, SWT.NONE);
		tblVwrClmnElectionEndDate.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : Converter.dateToString(((Election) element).getEndDate());
			}
		});
		TableColumn tblClmnElectionEndDate = tblVwrClmnElectionEndDate.getColumn();
		tblClmnElectionEndDate.setResizable(false);
		tblClmnElectionEndDate.setWidth(150);
		tblClmnElectionEndDate.setText("End Date");

		TableViewerColumn tblVwrClmnElectionStatus = new TableViewerColumn(tblVwrPollManage, SWT.NONE);
		tblVwrClmnElectionStatus.setLabelProvider(new ColumnLabelProvider() {
			public String getText(Object element) {
				return element == null ? "" : ((Election) element).getStatus().toString();
			}
		});
		TableColumn tblClmnElectionStatus = tblVwrClmnElectionStatus.getColumn();
		tblClmnElectionStatus.setWidth(100);
		tblClmnElectionStatus.setText("Status");

		tblVwrPollManage.setContentProvider(new ContentProvider() {
			@SuppressWarnings("unchecked")
			public Object[] getElements(Object inputElement) {
				return ((List<Election>) inputElement).toArray();
			}
		});
	}

	private void createPollManageTabButtons(Composite cmpPollManage) {
		Composite cmpPollManageButtons = new Composite(cmpPollManage, SWT.NONE);
		cmpPollManageButtons.setLayout(new FillLayout(SWT.VERTICAL));
		GridData gd_cmpPollManageButtons = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
		gd_cmpPollManageButtons.widthHint = 160;
		cmpPollManageButtons.setLayoutData(gd_cmpPollManageButtons);

		btnPollAddElection = new Button(cmpPollManageButtons, SWT.NONE);
		btnPollAddElection.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Election newElection = new Election();

				WzdAddEditElection wzdAddEditElection = new WzdAddEditElection(true, newElection);

				WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditElection);
				wzdDlg.open();

				if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
					manager.saveElection(newElection);
					refreshSelectedPage();
				}
			}
		});
		btnPollAddElection.setText("Add Election");

		btnPollEditElection = new Button(cmpPollManageButtons, SWT.NONE);
		btnPollEditElection.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Election selectedElection = getSelectedElection();
				if (selectedElection != null) {
					WzdAddEditElection wzdAddEditElection = new WzdAddEditElection(false, selectedElection);

					WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditElection);
					wzdDlg.open();

					if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
						try {
							selectedElection = manager.updateElection(selectedElection);
						} catch (WrongActionException e) {
							MessageDialog.openError(shlMain, "Error", e.getMessage());
						}
					}

					refreshSelectedPage();
				}
			}
		});
		btnPollEditElection.setText("Edit Election");

		btnPollDeleteElection = new Button(cmpPollManageButtons, SWT.NONE);
		btnPollDeleteElection.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Election selectedElection = getSelectedElection();
				if (selectedElection != null) {
					try {
						manager.deleteElection(selectedElection);
					} catch (ObjectDeleteException e) {
						MessageDialog.openError(shlMain, "Error", e.getMessage());
					}
					refreshSelectedPage();
				}
			}
		});
		btnPollDeleteElection.setText("Delete Election");

		new Label(cmpPollManageButtons, SWT.SEPARATOR | SWT.HORIZONTAL);

		btnPollSendElection = new Button(cmpPollManageButtons, SWT.NONE);
		btnPollSendElection.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Election selectedElection = getSelectedElection();
				if (selectedElection != null) {
					manager.sendElectionConfiguration(selectedElection);
				}
			}
		});
		btnPollSendElection.setText("Send Election");

		new Label(cmpPollManageButtons, SWT.SEPARATOR | SWT.HORIZONTAL);

		btnPollManageTokens = new Button(cmpPollManageButtons, SWT.NONE);
		btnPollManageTokens.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Election selectedElection = getSelectedElection();
				if (selectedElection != null) {
					TokenManagerWindow tokenManagerWindow = new TokenManagerWindow(shlMain, selectedElection);
					DialogPositioner.centerShell(tokenManagerWindow.shell);
					tokenManagerWindow.open();
				}
			}
		});
		btnPollManageTokens.setText("Manage Tokens");

		new Label(cmpPollManageButtons, SWT.SEPARATOR | SWT.HORIZONTAL);

		btnCheckElectionState = new Button(cmpPollManageButtons, SWT.NONE);
		btnCheckElectionState.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent event) {
				Election selectedElection = getSelectedElection();
				if (selectedElection != null) {
					dlgElectionState = new DlgElectionState(shlMain, selectedElection);
					dlgElectionState.open();
					dlgElectionState = null;
				}
			}
		});
		btnCheckElectionState.setText("Check Election state");

		new Label(cmpPollManageButtons, SWT.SEPARATOR | SWT.HORIZONTAL);

		btnCheckResults = new Button(cmpPollManageButtons, SWT.NONE);
		btnCheckResults.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				Election selectedElection = getSelectedElection();
				if (selectedElection != null) {
					System.out.println(manager.getElectionResult(selectedElection));
					ElectionBackend votingCard = (ElectionBackend) Converter.xmlToObject(selectedElection.getCards());
					DlgElectionResult dlgElectionResult = new DlgElectionResult(shlMain, votingCard, manager.getElectionResult(selectedElection));
					dlgElectionResult.open();
				}
			}
		});
		btnCheckResults.setText("Check results");
	}

	private void createPollCurrentTab(TabFolder tbFldPoll) {
		TabItem tbtmPollCurrent = new TabItem(tbFldPoll, SWT.NONE);
		tbtmPollCurrent.setText("Current");

		Composite cmpPollCurrent = new Composite(tbFldPoll, SWT.NONE);
		tbtmPollCurrent.setControl(cmpPollCurrent);
		cmpPollCurrent.setLayout(new GridLayout(2, false));
	}

	private void createStatusComposite() {
		Composite cmpStatus = new Composite(shlMain, SWT.NONE);
		cmpStatus.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
	}

	public static boolean isInDebugMode() {
		return ConfigPropertiesHolder.getInstance().getProperty(Property.DEBUG_STATE).equalsIgnoreCase("true");
	}

	private void onAddNode(Node selectedNode) {
		Node newNode = new Node();
		NodeType[] nodeTypes = getNodeTypes(selectedNode);

		WzdAddEditNode wzdAddEditNode = new WzdAddEditNode(true, newNode, nodeTypes);
		WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditNode);
		wzdDlg.open();

		if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
			newNode.setParent(selectedNode);
			manager.saveNode(newNode);
		}

		refreshSelectedPage();
	}

	private void onEditNode(Node selectedNode) {
		WzdAddEditNode wzdAddEditNode = new WzdAddEditNode(false, selectedNode, null);
		WizardDialog wzdDlg = new WizardDialog(shlMain, wzdAddEditNode);
		wzdDlg.open();

		if (wzdDlg.getReturnCode() == IDialogConstants.OK_ID) {
			manager.updateNode(selectedNode);
		}

		refreshSelectedPage();
	}

	private NodeType[] getNodeTypes(Node node) {
		NodeType[] nodeTypes;
		if (node.getLevel() == -1) {
			nodeTypes = new NodeType[] { NodeType.CKW };
		} else {
			switch (node.getNodeType()) {
			case CKW:
			case OKW:
				nodeTypes = new NodeType[] { NodeType.OKW, NodeType.RKW };
				break;
			case RKW:
			default:
				nodeTypes = new NodeType[] {};
				break;
			}
		}

		return nodeTypes;
	}

	private Node getSelectedCommunicationNode() {
		return (Node) ((StructuredSelection) treeVwrCommunicationNodes.getSelection()).getFirstElement();
	}

	private Member getSelectedDataMember() {
		return (Member) ((StructuredSelection) tblVwrDataMember.getSelection()).getFirstElement();
	}

	private Voter getSelectedDataVoter() {
		return (Voter) ((StructuredSelection) tblVwrDataVoter.getSelection()).getFirstElement();
	}

	private Election getSelectedElection() {
		return (Election) ((StructuredSelection) tblVwrPollManage.getSelection()).getFirstElement();
	}

	private Image createNodeStatusImage(int red, int blue, int green) {
		Image img = new Image(Display.getCurrent(), 50, 18);
		GC gc = new GC(img);
		Color insideColor = new Color(Display.getCurrent(), red, green, blue);
		gc.setBackground(insideColor);
		gc.fillRoundRectangle(16, 3, 15, 15, 5, 5);
		gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
		gc.drawRoundRectangle(16, 3, 14, 14, 5, 5);
		gc.dispose();
		return img;
	}

	public void refreshCommunicationNode(final Node node) {
		if (shlMain != null) {
			shlMain.getDisplay().syncExec(new Runnable() {
				@Override
				public void run() {
					if (treeVwrCommunicationNodes != null) {
						treeVwrCommunicationNodes.refresh(node);
					}
				}
			});
		}
	}

	public void refreshDlgElectionState(final Election election) {
		if (shlMain != null) {
			shlMain.getDisplay().syncExec(new Runnable() {
				@Override
				public void run() {
					if (dlgElectionState != null) {
						dlgElectionState.refreshElectionState(election);
					}
				}
			});
		}
	}

	public void refreshElectionPage() {
		if (shlMain != null) {
			shlMain.getDisplay().syncExec(new Runnable() {
				@Override
				public void run() {
					if (tblVwrPollManage != null) {
						tblVwrPollManage.setInput(manager.getAllElections());
					}
				}
			});
		}
	}

	public void refreshElection(final Election election) {
		if (shlMain != null) {
			shlMain.getDisplay().syncExec(new Runnable() {
				@Override
				public void run() {
					if (tblVwrPollManage != null) {
						tblVwrPollManage.refresh(election);
					}
				}
			});
		}
	}

	private void refreshSelectedPage() {
		switch (tbFldMain.getSelection()[0].getText()) {
		case "Communication":
			treeVwrCommunicationNodes.setInput(manager.getBaseNode());
			treeVwrCommunicationNodes.expandAll();
			break;
		case "Data":
			switch (tbFldData.getSelection()[0].getText()) {
			case "Member":
				tblVwrDataMember.setInput(manager.getAllMembers());
				break;
			case "Voter":
				tblVwrDataVoter.setInput(manager.getAllVoters());
				break;
			}
			break;
		case "Poll":
			switch (tbFldPoll.getSelection()[0].getText()) {
			case "Manage":
				tblVwrPollManage.setInput(manager.getAllElections());
				break;
			case "Current":
				break;
			}
			break;
		}
	}
}
